package ddz.logic.game;

import ch.qos.logback.classic.Logger;
import com.kaka.notice.Message;
import com.kaka.notice.annotation.Handler;
import ddz.constants.Crypto;
import ddz.constants.ErrCode;
import ddz.constants.ErrLevel;
import ddz.constants.OpCode;
import ddz.core.Table;
import ddz.core.TableState;
import ddz.core.Player;
import ddz.db.dao.TableDao;
import ddz.db.dao.UserDao;
import ddz.db.entity.ItemInfo;
import ddz.db.entity.UserInfo;
import ddz.db.service.CensusService;
import ddz.db.service.MatchMember;
import ddz.db.service.MatchResult;
import ddz.db.service.MatcherService;
import ddz.logic.ItemUtils;
import ddz.net.ProtocolMessage;
import ddz.numerical.manager.ConfPlaceInfoManager;
import ddz.numerical.pojo.ConfPlaceInfo;
import ddz.protos.GameReady;
import ddz.protos.GameRecovery;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 玩家准备
 *
 * @author zkpursuit
 */
@Handler(cmd = OpCode.cmd_ready, type = String.class)
public class ReadyHandler extends GetBenefitHandler {

    private static final Logger logger = (Logger) LoggerFactory.getLogger(ReadyHandler.class);

    @Override
    public void execute(ProtocolMessage msg) throws Exception {
        GameReady.CsReady csReady = (GameReady.CsReady) msg.getBody();
        int mode = csReady.getMode();
        int place = csReady.getPlace();
        boolean priorLookDiPai = csReady.getPriorLookDiPai();
        UserDao userDao = this.retrieveProxy(UserDao.class);
        UserInfo userInfo = userDao.getUserInfo(msg.uid());
        boolean updateUserInfo = false;
        ConfPlaceInfoManager confPlaceInfoManager = this.retrieveProxy(ConfPlaceInfoManager.class);
        ConfPlaceInfo confPlaceInfo = confPlaceInfoManager.getConfPlaceInfo(mode, place);
        if (confPlaceInfo != null) {
            if (userInfo.getGold() < confPlaceInfo.getMinGold()) {
                boolean flag = this.isCanGetBenefit(userInfo, true);
                if (flag) return;
            }
        }
        if (place <= 0) {
            confPlaceInfo = confPlaceInfoManager.getConfPlaceInfoByBounds(mode, userInfo.getGold());
        } else {
            confPlaceInfo = confPlaceInfoManager.getConfPlaceInfo(mode, place);
        }
        if (confPlaceInfo != null) {
            if (userInfo.getGold() < confPlaceInfo.getMinGold()) {
                sendError(msg.ctx(), opcode(), ErrLevel.WARN, ErrCode.gold_not_enough);
                return;
            }
        }
        if (priorLookDiPai) {
            List<ItemInfo> itemInfoList = ItemUtils.parseItemList(userInfo.getItems());
            boolean updateItems = ItemUtils.filterItems(itemInfoList);
            boolean isEnough = true;
            if (!ItemUtils.hasPropItem(itemInfoList, 9, 1)) {
                isEnough = false;
            }
            if (updateItems) {
                updateUserInfo = true;
            }
            if (!isEnough) {
                sendError(msg.ctx(), opcode(), ErrLevel.ERROR, ErrCode.dipaiKa_not_enough);
                return;
            }
        }
        CensusService censusService = this.retrieveProxy(CensusService.class);
        censusService.plus(mode, place, msg.uid());
        if (updateUserInfo) userDao.insertOrUpdateUser(userInfo);
        long deskId = userInfo.getDeskId();
        boolean gotoMatch = false;
        if (deskId <= 0) {
            gotoMatch = true;
        }
        TableDao tableDao = this.retrieveProxy(TableDao.class);
        if (deskId > 0) {
            Table table = tableDao.getDesk(deskId);
            if (table == null) {
                gotoMatch = true;
            } else {
                if (table.getState() == TableState.scrap) {
                    //已有玩家退出
                    gotoMatch = true;
                } else if (table.getState() == TableState.jiesuan
                        || table.getState() == TableState.none
                        || table.getState() == TableState.ready) {
                    Player player = table.getPlayerByUid(msg.uid());
                    if (!player.isReady()) {
                        player.setReady(true);
                        player.setPriorLookDiPai(priorLookDiPai);
                        Player[] members = table.getPlayers();
                        int count = 0;
                        long[] uids = new long[members.length];
                        for (int i = 0; i < members.length; i++) {
                            uids[i] = members[i].getUid();
                        }
                        for (Player member : members) {
                            if (member.isReady()) {
                                count++;
                            }
                        }
                        byte[] respBytes = GameReady.ScReady.newBuilder()
                                .setMode(mode)
                                .setPlace(place)
                                .setSeat(player.getSeatIndex())
                                .build().toByteArray();
                        for (int i = 0; i < members.length; i++) {
                            Player member = members[i];
                            this.sendData(member.getUid(), Crypto.isCrypto, opcode(), respBytes);
                        }
                        if (count == table.getMaxPlayers()) {
                            //全部已准备，调用创建房间的业务处理器，因本房间需要封存用作游戏记录，故本房间状态设置为废弃状态
                            table.setState(TableState.scrap);
                            tableDao.insertOrUpdateDesk(table);
                            MatchMember[] matchMembers = new MatchMember[uids.length];
                            for (int i = 0; i < matchMembers.length; i++) {
                                Player member = members[i];
                                if (member.isPriorLookDiPai()) {
                                    Map<String, Object> params = new HashMap<>(1);
                                    params.put("priorLookDiPai", priorLookDiPai);
                                    matchMembers[i] = new MatchMember(uids[i], 0, params);
                                } else {
                                    matchMembers[i] = new MatchMember(uids[i], 0, null);
                                }
                            }
                            MatchResult matchResult = new MatchResult(table.getMode(), table.getPlace(), matchMembers);
                            this.sendMessage(new Message(OpCode.cmd_create_desk, matchResult));
                        } else {
                            tableDao.insertOrUpdateDesk(table);
                            //Date date = new Date(System.currentTimeMillis() + 16000);
                            //quartzFacade.sendMessage(new Message(OpCode.timer_ready, player.getUid()), "player:" + player.getUid(), date);
                        }
                        return;
                    }
                } else {
                    //已经在对局中
                    byte[] reqBytes = GameRecovery.CsRecovery.newBuilder()
                            .setToken("")
                            .build().toByteArray();
                    sendMessage(new ProtocolMessage(Integer.parseInt(OpCode.cmd_recovery), reqBytes, userInfo.getUid()));
                    return;
                }
            }
        }
        if (gotoMatch) {
            byte[] respBytes = GameReady.ScReady.newBuilder()
                    .setMode(mode)
                    .setPlace(place)
                    .setSeat(-1)
                    .setPriorLookDiPai(priorLookDiPai)
                    .build().toByteArray();
            MatcherService matcherService = this.retrieveProxy(MatcherService.class);
            //quartzFacade.cancelQuartzSchedule(OpCode.timer_ready, "player:" + userInfo.getUid());
            if (!matcherService.isWaitingMatch(mode, place, userInfo.getUid())) {
                this.sendData(msg.uid(), Crypto.isCrypto, opcode(), respBytes);
//                quartzFacade.cancelQuartzSchedule(OpCode.timer_ready, "player:" + userInfo.getUid());
                Map<String, Object> params = new HashMap<>(1);
                params.put("priorLookDiPai", priorLookDiPai);
                matcherService.addWaitMatchPlayer(mode, place, userInfo.getUid(), userInfo.getScore(), params);
            }
        }

        //判断玩家所在房间的其他所有玩家都在房间内
        //如果都在，则仅为简单的准备，且进入准备倒计时，倒计时结束仍有玩家未准备则解散房间，进入匹配阶段

    }
}
